From 1e8193b5783676087bbd12da6be7641e40073168 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 25 Nov 2015 17:18:21 +0100 Subject: [PATCH] console: make printk() line continuation tracking per-CPU This avoids cases where split messages (with other than the initial part not carrying a log level; single line messages only of course) issued on multiple CPUs interfere with each other, causing messages to be issued which are supposed to be suppressed due to the log level setting. E.g. CPU A CPU B XENLOG_G_DEBUG "abc" XENLOG_G_DEBUG "def\n" "xyz\n" would cause the last message to be logged despite this obviously not being intended (at default log levels). Suggested-by: Boris Ostrovsky Signed-off-by: Jan Beulich Tested-by: Boris Ostrovsky Acked-by: Ian Campbell --- xen/drivers/char/console.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 4362400130..e0083f1cd4 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -620,15 +620,18 @@ static void printk_start_of_line(const char *prefix) static void vprintk_common(const char *prefix, const char *fmt, va_list args) { + struct vps { + bool_t continued, do_print; + } *state; + static DEFINE_PER_CPU(struct vps, state); static char buf[1024]; - static int start_of_line = 1, do_print; - char *p, *q; unsigned long flags; /* console_lock can be acquired recursively from __printk_ratelimit(). */ local_irq_save(flags); spin_lock_recursive(&console_lock); + state = &this_cpu(state); (void)vsnprintf(buf, sizeof(buf), fmt, args); @@ -637,30 +640,30 @@ static void vprintk_common(const char *prefix, const char *fmt, va_list args) while ( (q = strchr(p, '\n')) != NULL ) { *q = '\0'; - if ( start_of_line ) - do_print = printk_prefix_check(p, &p); - if ( do_print ) + if ( !state->continued ) + state->do_print = printk_prefix_check(p, &p); + if ( state->do_print ) { - if ( start_of_line ) + if ( !state->continued ) printk_start_of_line(prefix); __putstr(p); __putstr("\n"); } - start_of_line = 1; + state->continued = 0; p = q + 1; } if ( *p != '\0' ) { - if ( start_of_line ) - do_print = printk_prefix_check(p, &p); - if ( do_print ) + if ( !state->continued ) + state->do_print = printk_prefix_check(p, &p); + if ( state->do_print ) { - if ( start_of_line ) + if ( !state->continued ) printk_start_of_line(prefix); __putstr(p); } - start_of_line = 0; + state->continued = 1; } spin_unlock_recursive(&console_lock); -- 2.30.2